﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebPartPages;
using System.Collections.ObjectModel;
using System.Web.UI.WebControls;
using System.Web.UI;
using NT.SharePoint.RS.ReportingServiceWS;
using System.ComponentModel;
using NT.SharePoint.RS.WebParts.BO;
using NT.SharePoint.RS.WebParts.ToolParts;

namespace NT.SharePoint.RS.WebParts
{
    public class WPRSView : WebPart
    {
        [Browsable(false), WebPartStorage(Storage.Shared)]
        public string RSParameters { get; set; }

        [Browsable(false), WebPartStorage(Storage.Shared), DefaultValue(true)]
        public string ReportPath { get; set; }

        [Browsable(false), WebPartStorage(Storage.Shared), DefaultValue(true)]
        public bool DisplayReportToolPart { get; set; }

        List<IFilterValues> filterProviders = new List<IFilterValues>();

        [System.Web.UI.WebControls.WebParts.ConnectionConsumer("Report Parameters", "IFilterValues", AllowsMultipleConnections = true)]
        public void SetConnectionInterface(IFilterValues provider)
        {
            if (provider != null)
            {
                this.filterProviders.Add(provider);

                List<ConsumerParameter> parameters = new List<ConsumerParameter>();

                foreach (string param in this.GetStoredRSParameters().Keys)
                {
                    parameters.Add(new ConsumerParameter(param,
                    ConsumerParameterCapabilities.SupportsMultipleValues | ConsumerParameterCapabilities.SupportsAllValue));
                }

                provider.SetConsumerParameters(new ReadOnlyCollection<ConsumerParameter>(parameters));
            }
        }

        public override void CreateWebPartMenu()
        {
            base.CreateWebPartMenu();

            Microsoft.SharePoint.WebPartPages.MenuItem pi = new Microsoft.SharePoint.WebPartPages.MenuItem("RS Actions", "");
            pi.BeginSection = true;

            Microsoft.SharePoint.WebPartPages.MenuItem ami = new Microsoft.SharePoint.WebPartPages.MenuItem("Export to PDF", "RSExportPDF", new EventHandler(ExportToPdf));
            pi.MenuItems.Add(ami);

            this.WebPartMenu.MenuItems.Add(pi);
        }

        private void ExportToPdf(object sender, EventArgs args)
        {
            string url = GetIFrameUrl();

            this.Page.Response.Redirect(url + "&rs:Format=PDF");
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            string url = GetIFrameUrl();

            writer.Write(string.Format(@"<IFrame src=""{0}"" width=""100%"" height=""100%"" frameborder=""0"" scrolling=""auto""></IFrame>", url));
        }

        private string GetIFrameUrl()
        {
            Dictionary<string, RSParameter> parameters = GetRSParameters(true);

            string parametersUrl = "";

            if (parameters.Count > 0)
            {
                foreach (RSParameter param in parameters.Values)
                {
                    foreach (string val in param.GetValues())
                    {
                        parametersUrl = string.Concat(parametersUrl, "&", param.Name, "=", val);
                    }
                }
            }

            string url = string.Format("http://vpcmoss-en:81/ReportServer?{0}&rs:Command=Render&rc:toolbar={1}{2}",
                this.ReportPath, this.DisplayReportToolPart, parametersUrl);
            return url;
        }

        private string GetValuesAsString(ReadOnlyCollection<string> readOnlyCollection)
        {
            string result = "";

            if (readOnlyCollection != null)
            {
                foreach (var item in readOnlyCollection)
                {
                    result += "- " + item;
                }
            }

            return result;
        }

        public override ToolPart[] GetToolParts()
        {
            ToolPart[] toolParts = new ToolPart[4];
            toolParts[0] = new RSPropertiesToolPart();
            toolParts[1] = new RSParametersToolPart();
            toolParts[2] = new RSOptionsToolPart();
            toolParts[3] = new WebPartToolPart();

            return toolParts;
        }

        public Dictionary<string, RSParameter> GetRSParameters(bool cacheActivated)
        {
            return GetRSParameters(this.ReportPath, cacheActivated);
        }

        public Dictionary<string, RSParameter> GetRSParameters(string reportPath, bool cacheActivated)
        {
            Dictionary<string, RSParameter> result = new Dictionary<string, RSParameter>();

            if (cacheActivated && this.Page.Cache["RSParameters" + this.ID] != null)
            {
                result = (Dictionary<string, RSParameter>)this.Page.Cache["RSParameters" + this.ID];
            }
            else
            {
                Dictionary<string, ReportParameter> allParameters = GetAllRSParameters(reportPath);
                Dictionary<string, string> storedParameters = GetStoredRSParameters();

                foreach (string pName in allParameters.Keys)
                {
                    string value = storedParameters.ContainsKey(pName) ? storedParameters[pName] : "";
                    ReportParameter rp = allParameters[pName];

                    RSParameter rsPar = new RSParameter() { Name = pName, Values = value, Connected = false, MultipleValue = rp.MultiValue };
                    if (rp.ValidValues != null)
                    {
                        foreach (var vValue in rp.ValidValues)
                        {
                            rsPar.ValidValues.Add(vValue.Value, new RSParameter.RSParameterValidValue() { Value = vValue.Value, Label = vValue.Label });
                        }
                    }

                    result.Add(pName, rsPar);
                }

                this.Page.Cache["RSParameters" + this.ID] = result;
            }

            UpdateParametersListWithConnections(result);

            return result;
        }

        private void UpdateParametersListWithConnections(Dictionary<string, RSParameter> parameters)
        {
            foreach (IFilterValues filter in this.filterProviders)
            {
                if (filter.ParameterValues != null && filter.ParameterValues.Count > 0)
                {
                    if (parameters.ContainsKey(filter.ParameterName))
                    {
                        parameters[filter.ParameterName].Connected = true;

                        //Transform ReadOnlyArray to string
                        int tmpCount = 0;
                        string tmpValues = "";
                        foreach (string val in filter.ParameterValues)
                        {
                            if (tmpCount > 0)
                            {
                                tmpValues = string.Concat(tmpValues, ";");
                            }

                            tmpValues = string.Concat(tmpValues, val);

                            tmpCount++;
                        }
                        parameters[filter.ParameterName].Values = tmpValues;
                    }
                }
            }
        }

        private Dictionary<string, ReportParameter> GetAllRSParameters(string reportPath)
        {
            ReportingService rs = new ReportingService();
            //TODO: Get URL from Center
            rs.Credentials = System.Net.CredentialCache.DefaultCredentials;

            Dictionary<string, ReportParameter> parameters = new Dictionary<string, ReportParameter>();

            try
            {
                foreach (var item in rs.GetReportParameters(reportPath, null, true, null, null))
                {
                    parameters.Add(item.Name, item);
                }
            }
            catch (Exception)
            {

            }

            return parameters;
        }

        private Dictionary<string, string> GetStoredRSParameters()
        {
            Dictionary<string, string> tmpRSParameters = new Dictionary<string, string>();

            if (!string.IsNullOrEmpty(this.RSParameters))
            {
                System.Runtime.Serialization.Formatters.Binary.BinaryFormatter ser = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                System.IO.MemoryStream stream = new System.IO.MemoryStream();
                byte[] data = Convert.FromBase64String(this.RSParameters);
                stream.Write(Convert.FromBase64String(this.RSParameters), 0, data.Length);
                stream.Position = 0;
                tmpRSParameters = (Dictionary<string, string>)ser.Deserialize(stream);
            }

            return tmpRSParameters;
        }

        #region ICustomizeToolPane Members

        public void CreateToolPaneControls(ToolPane toolpane)
        {
            toolpane.InsertToolPart(0, new RSParametersToolPart());
            WebPartToolPart standardToolPart = new WebPartToolPart();
            toolpane.InsertToolPart(1, standardToolPart);
        }

        public bool ShowZoneIdentification()
        {
            return true;
        }

        public string ToolPaneTemplate
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }
}
